package com.hz.api.admin.web.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.hz.api.admin.common.exception.BizException;
import com.hz.api.admin.model.entity.LOLRankUsersEntity;
import com.hz.api.admin.model.request.AddOrEditLolUserRequest;
import com.hz.api.admin.model.request.AddOrEditLolUsersRequest;
import com.hz.api.admin.model.request.EditLolUserRequest;
import com.hz.api.admin.model.request.SetScoreRequest;
import com.hz.api.admin.model.vo.StartTeamingUpVO;
import com.hz.api.admin.web.service.LOLService;
import com.hz.api.admin.web.service.sql.LOLRankUsersService;
import com.hz.api.admin.web.util.TeamSplitterUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.hz.api.admin.web.util.TeamSplitterUtil.extractNames;
import static com.hz.api.admin.web.util.TeamSplitterUtil.findBestSplits;

@Service
@Slf4j
public class LOLServiceImpl implements LOLService {

    @Resource
    private LOLRankUsersService lolRankUsersService;

    private static Cache<String, StartTeamingUpVO> callableCache = CacheBuilder.newBuilder()
            //最大容量为100（基于容量进行回收）
            .maximumSize(100)
            //配置写入后多久使缓存过期-下文会讲述
            .expireAfterWrite(15, TimeUnit.MINUTES)
            //key使用弱引用-WeakReference
            .weakKeys()
            //当Entry被移除时的监听器
            .removalListener(notification -> System.out.println("notification=" + notification))
            //不指定CacheLoader
            .build();

    @Override
    public StartTeamingUpVO startTeamIngUp(List<String> names) {

        // 检查选中的玩家数量是否为10人
        if (names.size() != 10) {
            throw new BizException("人数应该固定为10人，请重新选择");
        }
        //名字组合排个序用作缓存key
        Collections.sort(names);
        StartTeamingUpVO startTeamingUpVO1 = null;
        try {
            for (String key : callableCache.asMap().keySet()) {
                StartTeamingUpVO startTeamingUpVO = callableCache.asMap().get(key);
                String jsonString = JSONObject.toJSONString(names);
                if (jsonString.equals(key)){
                    return startTeamingUpVO;
                }
            }
            startTeamingUpVO1 = callableCache.get(JSONObject.toJSONString(names),()->getStartTeamingUpVO(names));
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        return startTeamingUpVO1;
    }

    public StartTeamingUpVO getStartTeamingUpVO(List<String> names){
        StartTeamingUpVO startTeamingUpVO = new StartTeamingUpVO();

        // 从数据库中按分数排序获取所有玩家
        QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
        queryWrapper.orderByAsc("rank_sort");
        List<LOLRankUsersEntity> rankUsers = lolRankUsersService.list(queryWrapper);

        // 将玩家名字和他们的分数映射为Map
        Map<String, BigDecimal> rankMap = rankUsers.stream().collect(
                Collectors.toMap(LOLRankUsersEntity::getName, LOLRankUsersEntity::getCurrentScore));
        // 过滤出选中的玩家及其分数
        Map<String, Double> needRankMap = new HashMap<>();
        for (String name : names) {
            needRankMap.put(name, rankMap.get(name).doubleValue());
        }

        List<TeamSplitterUtil.Split> bestSplits = findBestSplits(needRankMap);
        TeamSplitterUtil.Split split = bestSplits.get(new Random().nextInt(bestSplits.size()));
        List<Map.Entry<String, Double>> team1 = split.getTeam1();
        List<Map.Entry<String, Double>> team2 = split.getTeam2();
        // 最终结果
        startTeamingUpVO.setTeam1(extractNames(team1));
        startTeamingUpVO.setTeam2(extractNames(team2));
        startTeamingUpVO.setDif("队伍1总分数" + team1.stream().mapToDouble(Map.Entry::getValue).sum() + ",队伍2的总分数" + team2.stream().mapToDouble(Map.Entry::getValue).sum());
        return startTeamingUpVO;
    }

    @Override
    public List<LOLRankUsersEntity> getLolRankUsers() {
        QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
        queryWrapper.orderByAsc("rank_sort");
        return lolRankUsersService.list(queryWrapper);
    }

    @Override
    public void setScore(SetScoreRequest names) {
        QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
        queryWrapper.in("name", names.getSelectedNames());
        List<LOLRankUsersEntity> lolRankUsers = lolRankUsersService.list(queryWrapper);
        if (CollectionUtils.isEmpty(lolRankUsers)) {
            throw new BizException("用户不存在");
        }
        lolRankUsers.stream().map(rank -> {
            rank.setCurrentScore(rank.getCurrentScore().add(names.getScore()));
            return rank;
        }).collect(Collectors.toList());

        for (LOLRankUsersEntity lolRankUser : lolRankUsers) {
            lolRankUsersService.updateById(lolRankUser);
        }
        updateRankSort();
        removeCache(names.getSelectedNames());
    }



    @Override
    public void addOrEditUser(AddOrEditLolUserRequest addOrEditLolUserRequest) {
        Long id = addOrEditLolUserRequest.getId();
        if (id == null){
            String name = addOrEditLolUserRequest.getName();
            QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
            queryWrapper.eq("name", name);
            LOLRankUsersEntity usersEntity = lolRankUsersService.getOne(queryWrapper);
            if (usersEntity != null) {
                throw new BizException("用户已经存在，不可重复添加");
            }

            LOLRankUsersEntity entity = new LOLRankUsersEntity();
            BeanUtil.copyProperties(addOrEditLolUserRequest, entity);
            lolRankUsersService.save(entity);
            updateRankSort();
        }else {
            LOLRankUsersEntity entity = new LOLRankUsersEntity();
            BeanUtil.copyProperties(addOrEditLolUserRequest, entity);
            lolRankUsersService.updateById(entity);
            updateRankSort();
            removeCache(Arrays.asList(addOrEditLolUserRequest.getName()));
        }

    }

    @Override
    public void deleteLOLUser(Long id) {
        lolRankUsersService.removeById(id);
        updateRankSort();
    }

    @Override
    public void editUser(EditLolUserRequest editLolUserRequest) {
        LOLRankUsersEntity entity = new LOLRankUsersEntity();
        BeanUtil.copyProperties(editLolUserRequest, entity);
        lolRankUsersService.updateById(entity);
    }

  @Override
  public void addOrEditUsers(AddOrEditLolUsersRequest request) {

    if (request.getSelectedNames() == null){
      throw new BizException("请勾选用户");
    }else {
      QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
      queryWrapper.in("name", request.getSelectedNames());
      List<LOLRankUsersEntity> lolRankUsers = lolRankUsersService.list(queryWrapper);
      if (CollectionUtils.isEmpty(lolRankUsers)) {
        throw new BizException("用户不存在");
      }
      if(request.getRecord().compareTo(BigDecimal.ZERO) == 1){
        lolRankUsers.stream().map(rank -> {
          rank.setVictoryNum(rank.getVictoryNum()+request.getRecord().intValue());
          return rank;
        }).collect(Collectors.toList());
      }else {
        lolRankUsers.stream().map(rank -> {
          rank.setDefeatsNum(rank.getDefeatsNum()+Math.abs(request.getRecord().intValue()));
          return rank;
        }).collect(Collectors.toList());
      }


      for (LOLRankUsersEntity lolRankUser : lolRankUsers) {
        lolRankUsersService.updateById(lolRankUser);
      }
      updateRankSort();
      removeCache(request.getSelectedNames());;
    }

  }


  public void updateRankSort() {
        QueryWrapper<LOLRankUsersEntity> queryWrapper = new QueryWrapper();
        queryWrapper.orderByDesc("current_score");
        List<LOLRankUsersEntity> rankUsers = lolRankUsersService.list(queryWrapper);
        List<LOLRankUsersEntity> updateEntityList = new ArrayList<>();
        for (int i = 0; i < rankUsers.size(); i++) {
            LOLRankUsersEntity entity = new LOLRankUsersEntity();
            entity.setId(rankUsers.get(i).getId());
            entity.setRankSort(i + 1);
            updateEntityList.add(entity);
        }
        lolRankUsersService.updateBatchById(updateEntityList);
    }

    //修改信息后删除缓存
    private void  removeCache(List<String> names){
        Set<String> keys = callableCache.asMap().keySet();
        for (String key : keys) {
            for (String name : names) {
                if (key.contains(name)){
                    callableCache.invalidate(key);
                }
            }
        }
    }
}
